
#include "string.h"
#include "hardware.h"
#include "OS.h"
#include "App.h"
#include "macros.h"
#include "Receivers.h"
#include "debug.h"
#include "modem.h"
#include "USART.h"
#include "SysClock.h"
#include "dev.h"
#include "app_menu.h"
#include "sscanf.h"
#include "storage.h"
#include "entrys.h"
#include "outp.h"
#include "sms.h"
#include "outp.h"
#include "cmdp.h"
#include "Sys.h"
#include "Analog.h"

unsigned int ModemStatus;
unsigned int TE_DirectModemMode;

char modem_buf[MODEM_BUFFER_SIZE];

int modem_registration;

const char* modem_cmd_init_list[] =
{
	"ATE0\rATE0",						  /* echo OFF */
							  /* echo OFF */
//SMS in TEXT mode;extended format reporting.Example instead of "RING" "+CREG: VOICE";
//SMS with indication(1) full indication + message(2)
	"AT+CMGF=1;+CRC=1;+CNMI=,1",
	"AT+CGSN",
	"AT+CLIP=1",
	"AT+MMICG=3",
	"AT+MMICV=2",
	//"AT+CLVL=7",					  /* volume 0 - 7 default 4 */
	"AT+CLVL=4",					  /* volume 0 - 7 default 4 */
//	"ATS96",
	"AT+CSQ",

#if defined(MODEM_TYPE__SIMCOM)
//	"AT+CENG=1",					  /* neighbouring cells */
	/* audio */
	"ATL3",						  /* Volume 0 - 3 */
	//"AT+CLVL=80\r",
	"AT+CLVL=100",
	//"AT+CMIC=0,15\r",
	"AT+CMIC=0,3",
	"AT+CMGDA=\"DEL READ\"",
#else
/* 	"AT+MAFEAT=1,1;+MAFEAT=2,1", */
/* 	"AT+MMICG=24;+MAVOL=1,1,5", */
	"AT+CMGD=1,4",
	"AT+CNMI=1,1",					  /* sms receive indication (+CMTI: "SM",1) */
#endif

	"END_OF_LIST"
};

int gIndex;

char *g_modem_cmd;

static void modem_rssi ( void )
{
	int rssi;
	char  *p;

	switch( APP.State )
	{
		case ASTE_START:
			OS_SET_TIMER(15000, ASTE_FINISH);
			APP.State = ASTE_SEND_TO_MODEM;
			break;

		case ASTE_SEND_TO_MODEM:
			if ( Modem_SendCommand(1,"AT+CSQ") == AR_SUCCSESS )
			{
				if ( (p=StrStr( modem_buf, "+CSQ: " )) )
				{
					s_scanf(p, "+CSQ: %d,", &rssi);

					OutSet(OUT_LED_1,  0xFFFFFFFF, 125, -1);
					OutSet(OUT_LED_2,  0xFFFFFFFF, 125, -1);
					OutSet(OUT_LED_3,  0xFFFFFFFF, 125, -1);

					if ( rssi < 99 )
					{
						//DBG("\n%s; ======>>> rssi: %d\n",__FUNCTION__,rssi); //Dima 					

						if( rssi > 7)
							OutSet(STATUS_LED, 0xF0F0F0F0, 125, -1);
						if( rssi > 13)
							OutSet(OUT_LED_3,  0xF0F0F0F0, 125, -1);
						if( rssi > 21)
							OutSet(OUT_LED_2,  0xF0F0F0F0, 125, -1);
						if( rssi > 28)
							OutSet(OUT_LED_1,  0xF0F0F0F0, 125, -1);
						
					}
 
				}

				if ( !modem_registration )
				{
					OS_SET_TIMER(5000, ASTE_FINISH);
				}

				OS_Sleep(1000);
			}
			break;

		case ASTE_FINISH:
			if ( modem_registration )
				STATUS_INDICATION(STATUS_MODEM_REG_OK);

			OutSet(OUT_LED_1,  0xFFFFFFFF, 125, -1);
			OutSet(OUT_LED_2,  0xFFFFFFFF, 125, -1);
			OutSet(OUT_LED_3,  0xFFFFFFFF, 125, -1);
			dbg("== FINISH =="); //Dima 
			APP.Result = AR_SUCCSESS;
			OS_Return();
			break;
	}

}


static void _Modem_SendCommand ( void )
{
	switch( APP.State )
	{
		case ASTE_START:
//			DBG("\n%s;", __FUNCTION__);
			OS_SET_TIMER(3000, ASTE_FINISH);

		case ASTE_RESET:
			APP.State = ASTE_SEND_COMMAND;
			break; 


		case ASTE_SEND_COMMAND:
			putstr(g_modem_cmd, DEV_MODEM);
			putch('\r', DEV_MODEM);
			dbg(">> SEND_COMMAND: %s",g_modem_cmd); 
			APP.State = ASTE_CHECK_MODEM_ANSWER;
			break;

		case ASTE_CHECK_MODEM_ANSWER:
			if ( Modem_Message )
			{
				//DBG("\n%s; Modem_Message: %s\n",__FUNCTION__,Modem_Message);
 
				if ( StrStr( Modem_Message, "\r\nOK\r\n" ) )
				{					
					APP.Result = AR_SUCCSESS;
					StrCpy(modem_buf, ModemBuffer);
					dbg("<OK> modem_buf: [%s]",modem_buf); 
					OS_Return();
				}
			}	
			break;

		case ASTE_FINISH:
			APP.Result = AR_FAIL;
			OS_Return();
			break;
	}
}

int Modem_SendCommand (int call_result, char *cmd )
{
	if ( cmd == NULL )
		return -1;
	
	g_modem_cmd = cmd;

	if ( !call_result )
	{
		OS_Call_App(0,_Modem_SendCommand);
		return 0;
	}

	if ( APP.CallResult )
	{
		APP.Result = APP.CallResult;
		APP.CallResult = 0;
		return APP.Result;
	}
	else
	{
		OS_Call_App(1,_Modem_SendCommand);
	}
	
	return 0;
}

void Modem_CheckRegistration ( void )
{
	switch( APP.State )
	{
		case ASTE_START:
			dbg("---"); //Dima
			OS_SET_TIMER(30000, ASTE_FINISH);
			APP.State = ASTE_SEND_TO_MODEM;
			break;

		case ASTE_SEND_TO_MODEM:
			if ( Modem_SendCommand(1,"AT+CREG?") == AR_SUCCSESS )
			{
				if ( StrStr( modem_buf, "+CREG: 0,1" ) || StrStr( modem_buf, "+CREG: 0,5" ))

/* #ifdef   MODEM_TYPE__SIMCOM */
/* 				if ( StrStr( modem_buf, "+CREG: 0,1" ) ) */
/* #else	 */
/* 				if ( StrStr( modem_buf, "+CREG: 000,001" ) ) */
/* #endif */
				{
					APP.Result = AR_SUCCSESS;
					OS_Return();
				}
				else
				{
					OS_Sleep(3000);
					APP.State = ASTE_SEND_TO_MODEM;
				}
			}
			break;

		case ASTE_FINISH:
			APP.Result = AR_FAIL;
			OS_Return();
			break;
	}
	
}

static void modem_registration_monitor ( void )
{
	switch( APP.State )
	{
	
		case ASTE_START:
			APP.State = ASTE_CHECK_REGISTRATION;
			OS_Sleep(30000);
			break;

		case ASTE_CHECK_REGISTRATION:
			if ( APP.CallResult )
			{
				APP.Result = APP.CallResult;

				if ( APP.CallResult == AR_SUCCSESS )
				{
					dbg("Registration: OK");
					modem_registration = TRUE;
					STATUS_INDICATION(STATUS_MODEM_REG_OK);
					APP.State = ASTE_START;
				}
				else
					if ( APP.CallResult == AR_FAIL )
					{
						dbg("===!!!>>> Registration: FAIL\n\r  >> Modem restart\n\r"); //Dima
						STATUS_INDICATION(STATUS_MODEM_NO_REG);
						modem_registration = FALSE;
						PIN_MODEM_POWER = FALSE;
						APP.State = ASTE_FINISH;
						OS_Sleep(4000);
					}

				APP.CallResult = 0;
			}
			else
			{
				OS_Call_App(1,Modem_CheckRegistration);
			}
			break;

		case ASTE_FINISH:
			Sys_Reset();
			/* OS_Run_App(Modem_Init); */
			/* OS_Run_App(modem_rssi); */
			/* OS_Return(); */
			break;
			
	}
}

#define   MAX_ERRORS		3	

int err_cnt;

void Modem_Init ( void )
{
	int res;

	switch( APP.State )
	{
		case ASTE_START:
			PIN_MODEM_POWER = FALSE;
			PIN_MODEM_POWER_DIR = PIN_OUTPUT;
			PIN_MODEM_POWER = FALSE;
			dbg("Modem power down"); //Dima
			OS_Sleep(500);
			APP.State = ASTE_MODEM_RESTART;
			modem_registration = FALSE;
			gIndex = 0;
			err_cnt = 0;
			break;

		case ASTE_MODEM_RESTART:
			PIN_MODEM_POWER = TRUE;
			PIN_MODEM_WAKEUP_DIR = PIN_OUTPUT;
			PIN_MODEM_WAKEUP = 0;
			STATUS_INDICATION(STATUS_MODEM_NO_REG);
			OS_Sleep(8000);
			dbg("Modem power up"); //Dima
			APP.State = ASTE_SEND_COMMAND;
			break;
		
		case ASTE_SEND_COMMAND:
			if ( StrCmp("END_OF_LIST", modem_cmd_init_list[gIndex]) )
			{
				//putsf(modem_cmd_init_list[gIndex], MODEM_PORT);
				if ( (res=Modem_SendCommand(1, (char*)((int)modem_cmd_init_list[gIndex]))) == AR_SUCCSESS )
					gIndex++;
				else
					if ( res == AR_FAIL )
					{
						if ( ++err_cnt > MAX_ERRORS )
						{
							Sys_Reset();
						}
						else
						{
							OS_Sleep(1500);
						}
					}
			}
			else
			{
				APP.State = ASTE_CHECK_REGISTRATION;
				OS_Run_App(modem_rssi);
			}
			break;

		case ASTE_CHECK_REGISTRATION:
			if ( APP.CallResult )
			{
				APP.Result = APP.CallResult;

				if ( APP.CallResult == AR_SUCCSESS )
				{
					dbg("Registration: OK"); //Dima
					modem_registration = TRUE;
					OS_Run_App(IncomingCallMonitor);
					OS_Run_App(sms_monitor);
					OS_Run_App(modem_registration_monitor);
//					OS_Run_App(app_achans);					
					APP.State = ASTE_FINISH;
					//OS_Send_Signal(modem_rssi, APP_SIGNAL_CLOSE);
				}
				else
					if ( APP.CallResult == AR_FAIL )
					{
						dbg("====!!!>>> Registration: FAIL\n  Modem restart\n\r"); //Dima
						PIN_MODEM_POWER = FALSE;
						OS_Send_Signal(modem_rssi, APP_SIGNAL_CLOSE);
						OS_Sleep(4000);
						APP.State = ASTE_START;
					}

				APP.CallResult = 0;

			}
			else
			{
				OS_Call_App(1,Modem_CheckRegistration);
			}
			break;

		case ASTE_FINISH:
			OS_Return();
			break;

		default:
			;

	}
  
}



incom_call_t	incom_call_inf; 

int incomming_call;

void IncomingCallMonitor( void )
{
	char *p;
	
	switch ( APP.State )
	{
		case ASTE_START:
			dbg(":started"); //Dima
			APP.State = ASTE_IDLE;
			
		case ASTE_IDLE:
			/* if ( Modem_Message ) */
			/* { */
			/* 	if ( StrStr(Modem_Message, "NO CARRIER") ) */
			/* 	{ */
			/* 		dbg("@@@@@ NO CARRIER");  */
			/* 		OS_Send_Signal(app_menu, APP_SIGNAL_CLOSE); */
			/* 	}  */
			/* } */

			if ( Modem_Message )
			{
				// +CLIP: "0523974963",129,"",128,"",0
				// +CLIP: "",129,"",,"",00

				if ( StrStr(Modem_Message, "NO CARRIER") )
				{
					dbg("@@@@@ NO CARRIER"); 
					OS_Send_Signal(app_menu, APP_SIGNAL_CLOSE);
				} 
				else
					if ( (p=StrStr(Modem_Message, "+CLIP:")) )
					{
						incomming_call = TRUE;
					
						s_scanf(p, "+CLIP: \"%s\"", incom_call_inf.phone);

						dbg("incomming call from: %s",incom_call_inf.phone); 

						modem_clear_buffer();
					}
					else
						if ( incomming_call == FALSE && StrStr(Modem_Message, ": VOICE") )
						{
							incomming_call = TRUE;
							incom_call_inf.phone[0] = 0;
						}
						else
							if ( StrStr(Modem_Message, ": RING") )
							{	
								//cmd_add_command("RS", DEV_SYS);
								Sys_Reset();  /* need reset because CLIP was not set  */
							}

				//modem_clear_buffer();
			}

			int addr;

			if ( incomming_call )
			{
				if ( incom_call_inf.phone[0] && (addr = storage.find(PHONE_LIST_1, incom_call_inf.phone)) > 0 )
				{
					dbg("Phone: %s was found in addr: 0x%X\n",incom_call_inf.phone, addr);
					incomming_call = 0;
					
					OUTP_SET(OUT_RELAY_4,3);
					OS_Sleep(1000);
					APP.State = ASTE_SEND_COMMAND;
					break;
				}
			
			}

			if ( incomming_call && Modem_SendCommand(1,"ATA") )
			{
				incomming_call = FALSE;
				OS_Run_App(app_menu);
			}
			break;

		case ASTE_SEND_COMMAND:
			if ( Modem_SendCommand(1,"ATH") )
			{
				APP.State = ASTE_IDLE;
			}
			break;	

		default:
			;
	}
}

